import logging
import os
import sys
from hashlib import md5

import pandas as pd
sys.path.append("..")
from MAPPING import list_file


# 本文件作用是统计ALIGN.xlsx的正确率，基准文件本目录下的其他xlsx文件
# 输入文件要求xlsx格式文件，切文件应在该目录下
# 表格须有Sheet1工作簿，且第一行为表头
# 表必须有“头实例”，“头实例属性”，“尾实例”，“尾实例属性”，“类型”，“标注”，“关系”

indexs = {}
relations = {}
param_not_ok = 0
record_count = 0
# True Positive(TP)：预测为正，实际为正
# False Positive(FP):：预测为正，实际为负
# False Negative(FN)：预测为负，实际为正
# Ture Negative(TN)：预测为负，实际为负
TP = 0
FP = 0
FN = 0
TN = 0

def process_row(df):
    global param_not_ok,record_count,TP,FP,FN,TN
    for index, row in df.iterrows():
        if type(row['标注']) is str:
            record_count += 1
            index = md5((row['头实例'] + row['尾实例'] + row['头实体属性值'] + row['尾实例属性值']).encode('utf-8')).hexdigest()
            if index not in indexs.keys():
                param_not_ok += 1
            r_index = md5((row['头实例'] + row['尾实例']).encode('utf-8')).hexdigest()
            if relations[r_index] == "use" and row['关系'] == "use" :
                TP+=1
            elif relations[r_index] == "use" and row['关系'] != "use" :
                FP+=1
            elif relations[r_index] != "use" and row['关系'] == "use" :
                FN+=1
            else:
                TN+=1


def map_file(pathBase, fileList):
    for i in range(0, len(fileList)):
        if fileList[i][0]== '~':
            continue
        logSTATIC.debug('第%d个文件' % i)
        file = os.path.join(pathBase, fileList[i])
        pd.set_option('display.max_columns', 1000)
        pd.set_option('display.max_rows', None)
        df = pd.read_excel(file, sheet_name="Sheet1")
        process_row(df)


def get_ALIGN():
    df = pd.read_excel("../ALIGN.xlsx", sheet_name="Sheet1")
    for index, row in df.iterrows():
        index = md5((row['头实例'] + row['尾实例'] + row['头实体属性值'] + row['尾实例属性值']).encode('utf-8')).hexdigest()
        indexs[index] = row
        r_index = md5((row['头实例'] + row['尾实例']).encode('utf-8')).hexdigest()
        relations[r_index] = row['关系']
    print("索引了%d条ALIGN数据"%len(indexs))


def printMetric():
    # 准确率（Precision）定义为：在单类预测结果中，正确的比率
    P = TP / (TP + FP)
    # 召回率（Recall）定义为：在单类的样本中，真正预测正确的比率
    R = TP / (TP + FN)
    # F1 Score定义为P和R的综合
    F1 = 2 * TP / (2 * TP + FP + FN)
    print("TP\tFP\tFN\tTN")
    print(f"{TP}\t{FP}\t{FN}\t{TN}")
    print("P\tR\tF1")
    print("%f\t%f\t%f"%(P,R,F1))
    print("参照集大小：%d" % record_count)
    print("参数准确数：%d" % (record_count - param_not_ok))
    print("关系准确数：%d" % (TP+TN))
    print("参数准确度：%f" % ((record_count - param_not_ok) / record_count))
    print("关系准确度：%f" % ((TP+TN) / record_count))



def main():
    fileList = list_file("./", ".xlsx")
    fileListSize = len(fileList)
    print("共找到%d个文件" % fileListSize)
    for i in range(0, 9 if 9 < fileListSize else fileListSize):
        print(fileList[i])
    print("...")
    get_ALIGN()
    map_file("./",fileList)
    printMetric()



if __name__ == '__main__':
    logSTATIC = logging.getLogger("CAP")
    logSTATIC.setLevel(logging.DEBUG)
    hdSTATIC = logging.FileHandler("CAP.log", mode='w', encoding='utf-8')
    hdSTATIC.setLevel(logging.DEBUG)
    logSTATIC.addHandler(hdSTATIC)
    main()